<?php

/**
 * Created by PhpStorm.
 * User: 小灰灰
 * Date: 2022-05-27
 * Time: 10:23:01
 * Info:
 * dump($spl_file->isValid()); // 文件是否有效，例如ture|false
 * dump($spl_file->getUploadExtension()); // 上传文件后缀名，例如'jpg'
 * dump($spl_file->getUploadMineType()); // 上传文件mine类型，例如 'image/jpeg'
 * dump($spl_file->getUploadErrorCode()); // 获取上传错误码，例如 UPLOAD_ERR_NO_TMP_DIR UPLOAD_ERR_NO_FILE UPLOAD_ERR_CANT_WRITE
 * dump($spl_file->getUploadName()); // 上传文件名，例如 'my-test.jpg'
 * dump($spl_file->getSize()); // 获得文件大小，例如 13364，单位字节
 * dump($spl_file->getPath()); // 获得上传的目录，例如 '/tmp'
 * dump($spl_file->getRealPath()); // 获得临时文件路径，例如 `/tmp/workerman.upload.SRliMu`
 */

namespace app\common\controller;

use support\Container;
use support\Request;
use app\common\model\UploadFile;
use think\Image;

class UploadController
{

    /**
     * 上传
     * 上传文件大小受到defaultMaxPackageSize限制，默认20M，可在后台设置-附件设置里面设置
     * @return void
     */
    public function upload($editorType = '', $isBase64 = false)
    {
        $request = request();
        if ($isBase64 === true) {
            //涂鸦上传（base64）
            $res = $this->upBase64($request->input('file'));

            return $res;
        } else {
            //普通上传
            foreach ($request->file() as $key => $spl_file) {
                $groupId    = $request->post('group_id', 0);
                $savePath   = $request->post('save_path', '');
                $editorType = $request->input('editor_type', '');
                if ($groupId == -1) {
                    $groupId = 0;
                }
                if ($editorType == 'iceEditor') {
                    $spl_file = $spl_file[0];
                }
                if ($spl_file && $spl_file->isValid()) {
                    $fileSize  = ($spl_file->getSize());
                    $getMime   = $spl_file->getUploadMineType();
                    $extension = $spl_file->getUploadExtension();
                    if (empty($savePath)) {
                        if (strstr($getMime, 'image')) {
                            $fileMime = "images";
                        } else {
                            $fileMime = "files";
                        }
                        $upload_types = $this->_get_upload_types($extension, $fileMime);
                        if ( ! $upload_types) {
                            return error_json('不允许上传 '.$extension.' 格式的文件');
                        }
                    } else {
                        $fileMime = $savePath;
                    }

                    $pathTime = date('Ymd');
                    $filePath = $fileMime."/".$pathTime."/";
                    $path     = public_path()."/uploads/".$filePath;
                    if ( ! is_dir($path)) {
                        @mkdir($path, 0777, true);
                    }
                    $fileName = substr(md5($spl_file->getUploadName().uniqid()), 8, 16).".".$extension;
                    $spl_file->move($path.$fileName);
                    $fileUrl = '/uploads/'.$filePath.$fileName;
                    $param   = [
                        'storage'   => 'local',
                        'group_id'  => $groupId,
                        'file_url'  => $fileUrl,
                        'file_name' => $fileName,
                        'file_size' => $fileSize,
                        'file_type' => $spl_file->getUploadMineType(),
                        'extension' => $extension
                    ];
                    if ($fileMime == 'images') {
                        //水印-图片
                        $this->add_water($fileUrl);
                        //写入数据库
                        $this->_att_write($param);
                    }
                    if ($editorType == 'ueditor') {
                        return json(['state' => 'SUCCESS', 'url' => $fileUrl]);
                    } elseif ($editorType == 'iceEditor') {
                        return json([['url' => $fileUrl, 'name' => $fileName, 'error' => 0]]);
                    } else {
                        return success_json('上传成功', ['url' => $fileUrl]);
                    }
                }
            }
        }

        //return response('ok');
    }

    /**
     * 写入数据库
     *
     * @param $param
     *
     * @return void
     */
    private function _att_write($param)
    {
        UploadFile::manageAdd($param);
    }

    //添加水印
    private function add_water($fileName)
    {
        //获取水印配置
        if (get_config('watermark_enable')) {
            $waterPic = public_path()."/static/water/".get_config('watermark_name');
            $picUrl   = public_path().$fileName;
            try {
                $image = Image::open($picUrl);
                $image->water($waterPic, get_config('watermark_position'),
                    get_config('watermark_touming'))->save($picUrl);
            } catch (\Exception $e) {
                return ['code' => 0, 'msg' => $e->getMessage()];
            }
        }
    }

    //上传类型
    private function _get_upload_types($ext, $type = 'images')
    {
        if ($type == 'images') {
            $arr = explode(',', get_config('upload_types_image'));
        } else {
            $arr = explode(',', get_config('upload_types_file'));
        }
        if ( ! in_array($ext, $arr)) {
            return false;
        }

        return true;

    }

    /**
     * editor上传服务配置项输出
     * @return array
     */
    public function ueditor_config(Request $request)
    {

        $config = $this->config_ueditor();
        $action = $request->get('action');
        switch ($action) {
            //图片上传
            case 'image':
                $editorType = "ueditor";

                return $this->upload($editorType);

            // 图片列表
            case 'listImage':
                $start = $request->get('start', 0);
                $size  = $request->get('size', 20);

                $list = $this->action_list($config, 'listImage', $start, $size);

                return $list;

            // 上传视频
            case 'video':
                $result = ['state' => 'ERROR', 'url' => ''];

                return $this->output($result);

            //文件上传
            case 'file':
                $editorType = "ueditor";

                return $this->upload($editorType);

            //文件列表
            case 'listFile':
                $start = $request->get('start', 0);
                $size  = $request->get('size', 20);

                $list = $this->action_list($config, 'listFile', $start, $size);

                return $list;

            // 涂鸦上传
            case 'crawl':
                $editorType = "ueditor";

                return $this->upload($editorType, true);
            default:
                return $this->output($config);
        }
    }

    private function config_ueditor()
    {
        $imageAllowFiles = get_config('upload_types_image');
        $imageAllowFiles = explode(',', $imageAllowFiles);
        foreach ($imageAllowFiles as $key => $v) {
            $imageAllowFiles[$key] = ".".$v;
        }
        $fileAllowFiles = get_config('upload_types_file');
        $fileAllowFiles = explode(',', $fileAllowFiles);
        foreach ($fileAllowFiles as $key => $v) {
            $fileAllowFiles[$key] = ".".$v;
        }

        $config = [
            // 上传图片配置项
            "imageActionName"         => "image",
            "imageFieldName"          => "file",
            "imageMaxSize"            => 1024 * 1024 * 10,
            "imageAllowFiles"         => $imageAllowFiles,
            "imageCompressEnable"     => true,
            "imageCompressBorder"     => 5000,
            "imageInsertAlign"        => "none",
            "imageUrlPrefix"          => "",

            // 涂鸦图片上传配置项
            "scrawlActionName"        => "crawl",
            "scrawlFieldName"         => "file",
            "scrawlMaxSize"           => 1024 * 1024 * 10,
            "scrawlUrlPrefix"         => "",
            "scrawlInsertAlign"       => "none",

            // 截图工具上传
            "snapscreenActionName"    => "snap",
            "snapscreenUrlPrefix"     => "",
            "snapscreenInsertAlign"   => "none",

            // 抓取
            "catcherLocalDomain"      => ["127.0.0.1", "localhost"],
            "catcherActionName"       => "catch",
            "catcherFieldName"        => "source",
            "catcherUrlPrefix"        => "",
            "catcherMaxSize"          => 1024 * 1024 * 10,
            "catcherAllowFiles"       => $imageAllowFiles,

            // 上传视频配置
            "videoActionName"         => "video",
            "videoFieldName"          => "file",
            "videoUrlPrefix"          => "",
            "videoMaxSize"            => 1024 * 1024 * 100,
            "videoAllowFiles"         => ['.mp4'],

            // 上传文件配置
            "fileActionName"          => "file",
            "fileFieldName"           => "file",
            "fileUrlPrefix"           => "",
            "fileMaxSize"             => 1024 * 1024 * 100,
            "fileAllowFiles"          => $fileAllowFiles,

            // 列出图片
            "imageManagerActionName"  => "listImage",   /* 执行图片管理的action名称 */
            "imageManagerListPath"    => "./public/uploads/images/",    /* 指定要列出图片的目录 */
            "imageManagerListSize"    => 20,    /* 每次列出文件数量 */
            "imageManagerUrlPrefix"   => "",    /* 图片访问路径前缀 */
            "imageManagerInsertAlign" => "none",    /* 插入的图片浮动方式 */
            "imageManagerAllowFiles"  => $imageAllowFiles, /* 列出的文件类型 */

            // 列出指定目录下的文件
            "fileManagerActionName"   => "listFile",
            "fileManagerListPath"     => "./public/uploads/files/",
            "fileManagerUrlPrefix"    => "",
            "fileManagerListSize"     => 20,
            "fileManagerAllowFiles"   => $fileAllowFiles

        ];

        return $config;
    }

    /**
     * 百度编辑输出
     */
    private function output($data)
    {
        return json($data);
    }

    /**
     * 百度编辑器列出文件
     */
    private function action_list($config, $type = 'listImage', $start = 0, $size = 20)
    {
        switch ($type) {
            case 'listImage':
                $allowFiles = $config['imageManagerAllowFiles'];
                $path       = $config['imageManagerListPath'];
                break;
            case "listFile":
                $allowFiles = $config['fileManagerAllowFiles'];
                $path       = $config['fileManagerListPath'];
                break;
        }
        $allowFiles = substr(str_replace(".", "|", join("", $allowFiles)), 1);
        /* 获取参数 */
        $end = $start + $size;
        /* 获取文件列表 */
        $files = $this->getfiles($path, $allowFiles);

        if ( ! empty($files) && ! count($files)) {
            return json_encode(array(
                "state" => "no match file",
                "list"  => array(),
                "start" => $start,
                "total" => count($files)
            ));
        }
        /* 获取指定范围的列表 */
        $len = count($files);
        for ($i = min($end, $len) - 1, $list = []; $i < $len && $i >= 0 && $i >= $start; $i--) {
            $list[] = $files[$i];
        }
        $list = arrayOrder($list, 'mtime');

        /* 返回数据 */
        $result = json_encode(array(
            "state" => "SUCCESS",
            "list"  => $list,
            "start" => $start,
            "total" => count($files)
        ));

        return $result;

    }

    /**
     * 处理base64编码的图片上传
     * @return mixed
     */
    private function upBase64($fileField)
    {
        $base64_image_content = $fileField;
        if (empty($base64_image_content)) {
            return false;
        }
        //合成图片的base64编码成
        $base64_image_content = "data:image/png;base64,{$base64_image_content}";
        //匹配出图片的信息
        $match = preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result);
        if ( ! $match) {
            return false;
        }

        //解码图片内容(方法一)
        /*$base64_image = preg_split("/(,|;)/",$base64_image_content);
        $file_content = base64_decode($base64_image[2]);
        $file_type = substr(strrchr($base64_image[0],'/'),1);*/

        //解码图片内容(方法二)
        $base64_image = str_replace($result[1], '', $base64_image_content);
        $file_content = base64_decode($base64_image);
        $file_type    = $result[2];

        //如果没指定目录,则保存在当前目录下
        $pathTime = date('Ymd');
        $filePath = "/uploads/crawl/".$pathTime."/";
        $path     = public_path().$filePath;
        if ( ! is_dir($path)) {
            @mkdir($path, 0777, true);
        }
        $file_name = time().".{$file_type}";

        $new_file = $path.$file_name;

        if (file_exists($new_file)) {
            //有同名文件删除
            @unlink($new_file);
        }
        if (file_put_contents($new_file, $file_content)) {
            return json_encode(['state' => 'SUCCESS', 'url' => $filePath.$file_name]);
        }

        return false;
    }

    /**
     * 遍历获取目录下的指定类型的文件
     *
     * @param       $path
     * @param array $files
     *
     * @return array
     */
    /**
     * 遍历获取目录下的指定类型的文件
     *
     * @param       $path
     * @param array $files
     *
     * @return array
     */
    function getfiles($path, $allowFiles, &$files = array())
    {
        if ( ! is_dir($path)) {
            return null;
        }
        if (substr($path, strlen($path) - 1) != '/') {
            $path .= '/';
        }
        $handle = opendir($path);
        while (false !== ($file = readdir($handle))) {
            if ($file != '.' && $file != '..') {
                $path2 = $path.$file;
                if (is_dir($path2)) {
                    $this->getfiles($path2, $allowFiles, $files);
                } else {
                    if (preg_match("/\.(".$allowFiles.")$/i", $file)) {
                        $files[] = array(
                            'url'   => str_replace("./public", "", substr($path2, strlen($_SERVER['DOCUMENT_ROOT']))),
                            'mtime' => filemtime($path2)
                        );
                    }
                }
            }
        }
        $files = arrayOrder($files, 'mtime');

        return $files;
    }

}
